home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Aminet 2
/
Aminet AMIGA CDROM (1994)(Walnut Creek)[Feb 1994][W.O. 44790-1].iso
/
Aminet
/
mus
/
play
/
DES_Tracker2_00.lha
/
DTL
/
code
/
MODInfo.S
< prev
Wrap
Text File
|
1993-12-17
|
29KB
|
1,237 lines
;;=======================================================================;;
;; MODInfo.S -> Begun: Tue, Feb 9, 1993 ;;
;; Last updated: Sat, Dec 18, 1993 ;;
;;-----------------------------------------------------------------------;;
;; This is v2.0 of the Module Info Utility for destracker.library v3.0+ ;;
;;-----------------------------------------------------------------------;;
;; Designed and written by Darren E. Schebek ;;
;; Copyright ©1993 by Darren E. Schebek ;;
;; All rights reserved. ;;
;;-----------------------------------------------------------------------;;
;; This source code is NOT public domain ;;
;;=======================================================================;;
INCLUDE "dp:system.gs" ;DevPac-specific global include thingy.
INCLUDE "DTLib.I" ;DES-Tracker include file.
;---------------------------------------------------------------
; System equates...
_SYSBase = 4 ;Pointer to exec library base.
;---------------------------------------------------------------
; Control character equates used in text strings and in string parsing...
NULL = $00 ;NULL
TAB = $09 ;TAB
LF = $0A ;Linefeed
DQUOTE = $22 ;Double quote
;---------------------------------------------------------------
; Some custom macros of my own...
LOADLIB MACRO
MOVE.L _\1Base,A6
ENDM
SYS MACRO
JSR _LVO\1(A6)
ENDM
BYTETAB MACRO
\1 EQU SOFFSET
SOFFSET SET SOFFSET+\2
ENDM
;---------------------------------------------------------------
; Variables used by the MINFO program...
STRUCTURE MINFO_VARS,0
UBYTE LoadFlag
UBYTE Dummy
APTR MyTaskPtr ;Points to my Task control structure.
APTR MyFileInfoBlock ;Ptr to a FileInfoBlock structure.
APTR DosBase ;Ptr to dos.library base.
APTR DTBase ;Ptr to destracker.library base.
LONG SaveD0
BPTR OutputHandle ;Ptr to standard output handle.
BPTR LockPointer
ULONG PlayTime ;Calc'ed play time for the song.
STRUCT TimeScan,tsi_SIZE ;TIMESCANINFO struct for CalcElapsedTime().
BYTETAB FilenameString,128 ;Workspace for string handling.
BYTETAB DecString,12 ;Holds decimal string of longword values.
BYTETAB TimeString,16 ;Holds converted time string for play time.
LABEL MINFO_SIZE ;Equates to size of required var space.
;---------------------------------------------------------------
; The beginning. Start out by allocating space for my program variables,
; initialize the program, and then proceed to parse the command line
; arguments...
Main Move.L A0,A5 ;Cache argstring pointer in A3 for now.
MoveQ #10,D7 ;D7 holds exit code in case of error.
; Allocate space for program variables...
LOADLIB SYS ;Get SYS_Base in A6.
Move.L #MINFO_SIZE,D0 ;Size of variable space I need.
Move.L #MEMF_CLEAR,D1 ;Initialize everything to 0 for me.
SYS AllocMem ;Attempt to allocate variable space.
Tst.L D0 ;Error?
Ble ProgAbort ;Yup, what a washout.
Move.L D0,A4 ;Nobody's allowed to touch A4!
Sub.L A1,A1
SYS FindTask
Move.L D0,MyTaskPtr(A4)
Move.L #fib_SIZEOF,D0 ;Size of the structure.
Move.L #MEMF_CLEAR,D1 ;Clear it out for me, please.
SYS AllocMem ;Attempt to allocate.
Move.L D0,MyFileInfoBlock(A4) ;Did it work?
Bne .1 ;Yup, continue.
Move.L #InsuffMemText,D2 ;Nope, insufficient memory.
Bra .PrintGo ;Tell user and abort.
; Open DOS Library...
.1 LOADLIB SYS
Lea DosName,A1
MoveQ #0,D0
SYS OpenLibrary
Move.L D0,DosBase(A4)
; Get handle of standard output...
Move.L D0,A6 ;Get output handle for text output.
SYS Output
Move.L D0,OutputHandle(A4) ;Save ptr to std. output handle.
; Open DES-Tracker library...
.OpenDT LOADLIB SYS
Lea DTLName,A1 ;"destracker.library".
MoveQ #3,D0 ;Must be version 3.0+ of library.
SYS OpenLibrary ;Attempt to open destracker.library.
Move.L D0,DTBase(A4) ;Store pointer to library base.
Bne .2 ;If <>0 then open succeeded.
Move.L #NoLibOpenText,D2 ;Say "couldn't open lib..."
.PrintGo Bsr PrintNicely ;Abort with error.
Bra Abort
;-------------------------------
; Initialization complete. Now check for command line argument...
.2 Bsr GetFileSpec
Tst.L D0
Beq .IsQMark
Bpl .HaveFileSpec ;Load module and report statistics.
Bra .NoFileSpec ;Report stats on currently loaded mod.
.IsQMark Move.L #HelloText,D2 ;Say hello and don't report anything.
Bsr PrintNicely ;Nicely means you can pause text output.
Bra .Done ;And just leave.
; Here, I have to load a specified song into the library and then report the
; results. First, though, I have to make sure it's a legitimate filename spec...
.HaveFileSpec Lea FilenameString(A4),A0
Bsr VerifyPath
Tst.L D0
Beq .LoadFile ;Legitimate filespec, go load module.
Bpl .NotFile
Move.L #NotFoundErr,D2
Bra .PrintGo
.NotFile Move.L #NotFileText,D2
Bra .PrintGo
.LoadFile St LoadFlag(A4)
Move.L DTBase(A4),A6
Lea FilenameString(A4),A0
SYS LoadModule
Tst.L D0
Bpl .NoFileSpec ;Now report on module just loaded.
Bsr ReportLibErr ;Tell user why mod couldn't be loaded.
Bra Abort
; Here I have a module in memory that I must report statistics on, so I
; report statistics on it...
.NoFileSpec Move.L DTBase(A4),A5
BTst #DF_MODULELOADED,dtl_Flags+1(A5)
Bne .IsMod
Move.L #NoModuleText,D2
Bra .PrintGo
.IsMod
; Calculate the play time for the song module...
Lea TimeScan(A4),A0
Move.B dtl_StartPosition(A5),tsi_StartPos(A0)
Move.B dtl_StartNoteIndex(A5),tsi_StartNote(A0)
Move.B dtl_EndPosition(A5),tsi_EndPos(A0)
Move.B dtl_EndNoteIndex(A5),tsi_EndNote(A0)
Move.B dtl_DefaultTempo(A5),tsi_DefaultTempo(A0)
Move.B dtl_FineTempo(A5),tsi_FineTempo(A0)
MoveQ #0,D0
Tst.B dtl_TimingMode(A5)
Beq .CET1
BSet #TSIB_TIMINGMODE,D0
.CET1 BTst #DF_TEMPOINT-8,dtl_Flags2(A5)
Beq .CET2
BSet #TSIB_TEMPOINTERP,D0
.CET2 Cmp.B #1,dtl_DefIterations(A5)
Bls .CET3
.DoConsecIter BSet #TSIB_MULTIPLEITERS,D0
.CET3 Move.B D0,tsi_Flags(A0)
Move.L A6,-(Sp)
Move.L A5,A6
SYS CalcElapsedTime
MoveQ #64,D0
MoveQ #0,D1
MoveQ #10,D2
SYS CalcVolFadeTime
Move.L D0,PlayTime(A4)
Move.L (Sp)+,A6
Lea TimeScan(A4),A0
MoveQ #0,D1
Move.B dtl_DefIterations(A5),D1
Cmp.B #1,D1
Bhi .Multi
Blo .Multi
; Store time for 1 iteration only...
Move.L tsi_FirstIterTime(A0),PlayTime(A4)
Bra .DonePlayTime
; Calculate time for multiple iterations...
.Multi Move.L PlayTime(A4),D0
Add.L tsi_FirstIterTime(A0),D0
Move.L tsi_ConsecIterTime(A0),D2
Bra .CET4
.AddLoop Add.L D2,D0
.CET4 SubQ #1,D1
Bgt .AddLoop
Move.L D0,PlayTime(A4)
.DonePlayTime Move.L #ModInfoForFile,D2
Bsr PrintN2Text
Bne AbortControlC
Move.L dtl_ModuleStatus+ms_Filename(A5),D2
Bsr PrintNText
Bne AbortControlC
; Print title of song...
Move.L #TitleText,D2
Bsr PrintN2Text
Bne AbortControlC
Move.L dtl_ModuleStatus+ms_Name(A5),D2
Bsr PrintNText
Bne AbortControlC
; Print the play time for the song...
Move.L #PTimeText,D2
Bsr PrintN2Text
Bne AbortControlC
Move.L PlayTime(A4),D0
Bsr BinToTime
Lea TimeString(A4),A0
Move.L A0,D2
Bsr PrintNText
Bne AbortControlC
; Print length of the file...
Move.L #FLengthText,D2
Bsr PrintN2Text
Bne AbortControlC
Move.L dtl_ModuleStatus+ms_Length(A5),D0
Bsr BinToDec
Lea DecString(A4),A0
Bsr StripLeadingZeros
Move.L A0,D2
Bsr PrintNText
Bne AbortControlC
; Print format of the module file...
Move.L #FormatText,D2
Bsr PrintN2Text
Bne AbortControlC
Move.L #STFormat,D2
Cmp.B #MF_SOUNDTRACKER,dtl_ModuleStatus+ms_Format(A5)
Beq .RS1
Move.L #NTFormat,D2
Cmp.B #MF_NOISETRACKER,dtl_ModuleStatus+ms_Format(A5)
Beq .RS1
Move.L #DTFormat,D2
.RS1 Bsr PrintNText
Bne AbortControlC
; Say whether file has a PSC0 construct or not...
Move.L #HasPSC0Text,D2
Bsr PrintN2Text
Bne AbortControlC
Move.L #YesText,D2
BTst #DF_HASPSC0-8,dtl_Flags2(A5)
Bne .RS2
Move.L #NoText,D2
.RS2 Bsr PrintNText
Bne AbortControlC
; Indicate base timing...
Move.L #BaseTimingText,D2
Bsr PrintN2Text
Bne AbortControlC
Move.L #UnknownText,D2
BTst #DF_HASPSC0-8,dtl_Flags2(A5)
Beq .RS3
Move.L #NTSCText,D2
Tst.B dtl_TimingMode(A5)
Beq .RS3
Move.L #PALText,D2
.RS3 Bsr PrintNText
Bne AbortControlC
; Report tempo interpretation...
Move.L #TempoIntText,D2
Bsr PrintN2Text
Bne AbortControlC
Move.L #StandardText,D2
BTst #DF_TEMPOINT-8,dtl_Flags2(A5)
Bne .RS4
Move.L #BPMText,D2
.RS4 Bsr PrintNText
Bne AbortControlC
; Report default tempo...
Move.L #DefTempoText,D2
Bsr PrintN2Text
Bne AbortControlC
MoveQ #0,D0
Move.B dtl_DefaultTempo(A5),D0
Bsr BinToDec
Lea DecString(A4),A0
Bsr StripLeadingZeros
Move.L A0,D2
Bsr PrintNText
Bne AbortControlC
; Report default fine tempo...
Move.L #DefFTempoText,D2
Bsr PrintN2Text
Bne AbortControlC
MoveQ #0,D0
Move.B dtl_FineTempo(A5),D0
Bpl .RS8
Neg.B D0
Move.L D0,-(Sp)
Move.L #MinusText,D2
MoveQ #1,D3
Bsr PrintCLI
Bne AbortControlC
Move.L (Sp)+,D0
.RS8 Bsr BinToDec
Lea DecString(A4),A0
Bsr StripLeadingZeros
Move.L A0,D2
Bsr PrintNText
Bne AbortControlC
; Report Iterations...
Move.L #IterationsText,D2
Bsr PrintN2Text
Bne AbortControlC
MoveQ #0,D0
Move.L #InfiniteText,D2
Move.B dtl_DefIterations(A5),D0
Beq .RS5
Bsr BinToDec
Lea DecString(A4),A0
Bsr StripLeadingZeros
Move.L A0,D2
.RS5 Bsr PrintNText
Bne AbortControlC
; Report number of patterns...
Move.L #NumPattsText,D2
Bsr PrintN2Text
Bne AbortControlC
MoveQ #0,D0
Move.W dtl_ModuleStatus+ms_NumPatterns(A5),D0
Bsr BinToDec
Lea DecString(A4),A0
Bsr StripLeadingZeros
Move.L A0,D2
Bsr PrintNText
Bne AbortControlC
; Report number of positions...
Move.L #NumPosText,D2
Bsr PrintN2Text
Bne AbortControlC
MoveQ #0,D0
Move.W dtl_ModuleStatus+ms_NumPositions(A5),D0
Bsr BinToDec
Lea DecString(A4),A0
Bsr StripLeadingZeros
Move.L A0,D2
Bsr PrintNText
Bne AbortControlC
; Report number of instruments...
Move.L #NumInstsText,D2
Bsr PrintN2Text
Bne AbortControlC
Lea dtl_ModuleStatus+ms_Instruments(A5),A0
MoveQ #0,D0
.RS6 Tst.L (A0)
Beq .RS7
Move.L (A0),A0
AddQ #1,D0
Bra .RS6
.RS7 Move.L D0,SaveD0(A4)
Bsr BinToDec
Lea DecString(A4),A0
Bsr StripLeadingZeros
Move.L A0,D2
Bsr PrintNText
Bne AbortControlC
Move.L SaveD0(A4),D0
; Now report instrument data...
Tst.B D0 ;Any instruments to report?
Beq .Done ;Nope.
Move.L #InstDataText,D2
Bsr PrintNText
Bne AbortControlC
Move.L dtl_ModuleStatus+ms_InstInfoBlocks(A5),A3
MoveQ #1,D4
MoveQ #31-1,D5
.ILoop Tst.W 22(A3)
Bne .GoodInst
Tst.B (A3)
Beq .NextInstrument
.GoodInst MoveQ #0,D0
Move.L D4,D0
MoveQ #4,D1
Bsr PrintDecRJust
Bne AbortControlC
MoveQ #4,D0
Bsr PrintNSpaces
Bne AbortControlC
Move.L A3,D2
MoveQ #22,D0 ;Don't print more than 22 characters.
Bsr PrintTextMax
Bne AbortControlC
Move.W D0,D1
MoveQ #24,D0
Sub.W D1,D0
Bsr PrintNSpaces
Bne AbortControlC
Move.L #0,D0
Move.W 22(A3),D0
Bne .IsUsed
Move.L #UnusedText,D2
Bsr PrintNicely
Bne AbortControlC
Bra .NextInstrument
.IsUsed Add.L D0,D0
MoveQ #7,D1
Bsr PrintDecRJust
Bne AbortControlC
MoveQ #3,D0
Bsr PrintNSpaces
Bne AbortControlC
MoveQ #0,D0
Move.W 26(A3),D0
Add.L D0,D0
MoveQ #7,D1
Bsr PrintDecRJust
Bne AbortControlC
MoveQ #2,D0
Bsr PrintNSpaces
Bne AbortControlC
MoveQ #0,D0
Move.W 28(A3),D0
Add.L D0,D0
MoveQ #7,D1
Bsr PrintDecRJust
Bne AbortControlC
MoveQ #4,D0
Bsr PrintNSpaces
Bne AbortControlC
MoveQ #0,D0
Move.B 25(A3),D0
MoveQ #2,D1
Bsr PrintDecRJust
Bne AbortControlC
Move.L #LineFeed,D2
MoveQ #1,D3
Bsr PrintCLI
.NextInstrument AddQ.W #1,D4
Lea 30(A3),A3
DBra D5,.ILoop
.InstsDone Move.L #LineFeed,D2
MoveQ #1,D3
Bsr PrintCLI
Bsr PrintSampleTexts
.Done Move.L DTBase(A4),A6
Tst.B LoadFlag(A4)
Beq .Go
SYS UnloadModule ;Unload mod if I had to load it myself.
.Go MoveQ #0,D7
;-------------------------------
; Deallocate everything and leave...
Abort LOADLIB SYS ;Get SYS_Base.
Move.L MyFileInfoBlock(A4),D0
Beq .1 ;Wasn't allocated.
Move.L D0,A1
Move.L #fib_SIZEOF,D0
SYS FreeMem
.1 Move.L DTBase(A4),D0 ;DES-Tracker lib base ptr.
Beq .4 ;It didn't open.
Move.L D0,A1 ;It is open.
SYS CloseLibrary ;Close it.
.4 Move.L DosBase(A4),D0
Beq .5
Move.L D0,A1
SYS CloseLibrary
.5 Move.L A4,A1 ;Release program variable space.
Move.L #MINFO_SIZE,D0 ;Size of variable space.
SYS FreeMem ;Free it.
Leave Move.L D7,D0 ;Return exit code in D0.
Rts
ProgAbort MoveQ #10,D7 ;Error exit code in D7.
Bra Leave ;Abort with error.
;---------------------------------------------------------------
AbortControlC Move.L #UserAbortText,D2
Bsr PrintNText
Bra Abort
UserAbortText Dc.B LF,LF,"*** User abort. ***",LF,LF,0
Even
;---------------------------------------------------------------
; Determines if a given sample is a valid sampletext.
;
; Input: A0 = Pointer to an INSTSTATUS structure.
;
; Output: D0 = non-zero if instrument is NOT a valid sampletext, zero if it
; IS a valid sampletext.
;
CheckIfSampleText
MoveM.L D1-D4/A0-A3,-(Sp)
Move.L is_Address(A0),A1
Move.L is_Length(A0),D0
MoveQ #-1,D2
Cmp.L #8,D0
Blt .NoGood ;8 bytes or less - can't be a sampletext.
SubQ.L #4,D0
AddQ.W #4,A1
; Valid range for SampleText chars: $20-$7F inclusive, $09, $0A, $0D
; All other values invalidate instrument data as a SampleText...
.1 Move.B (A1)+,D1
Bmi .NoGood
Beq .2
Cmp.B #$09,D1
Beq .2
Cmp.B #$0A,D1
Beq .2
Cmp.B #$0D,D1
Beq .2
Cmp.B #$20,D1
Blt .NoGood
.2 SubQ.L #1,D0
Bne .1
MoveQ #0,D2 ;It's a sampletext.
.NoGood Move.L D2,D0
MoveM.L (Sp)+,D1-D4/A0-A3
Rts
;---------------------------------------------------------------
PrintSampleTexts
Move.L dtl_ModuleStatus+ms_Instruments(A5),A3
Bra .NextInst
.InstLoop Move.L D0,A3
Move.L D0,A0
Bsr CheckIfSampleText
Tst.W D0
Bne .NextInst
Move.L #PSampleText,D2
Bsr PrintN2Text
Move.L is_Name(A3),D2
Bsr PrintN2Text
Move.l #CloseQText,D2
Bsr PrintN2Text
Move.L is_Address(A3),A2
Move.L is_Length(A3),D3
AddQ.W #4,A2
SubQ.L #4,D3
.1 Tst.B (A2)
Bne .2
AddQ.W #1,A2
SubQ.L #1,D3
Bra .1
.2 Move.L A2,D2
Bsr PrintNicely
.3 SubQ.L #1,D3
Ble .DoLF
Tst.B (A2)+
Bne .3
Bra .1 ;Hit a NULL, skip it and print rest of sampletext.
.DoLF Move.L #LFd,D2
MoveQ #1,D3
Bsr PrintCLI
.NextInst Move.L (A3),D0
Bne .InstLoop
.Done Rts
LFd Dc.B LF,LF,0
PSampleText Dc.B 'Showing Sample Text: "',NULL
CloseQText Dc.B '"...',LF,LF,NULL
Even
;---------------------------------------------------------------
PrintDecRJust MoveM.L D0-D1/A0-A3,-(Sp)
Bsr BinToDec
Lea DecString(A4),A0
Bsr StripLeadingZeros
Move.L A0,A1
MoveQ #-1,D0
.1 AddQ #1,D0
Tst.B (A1)+
Bne .1
Sub.W D0,D1
Move.W D1,D0
Bsr PrintNSpaces
Bne .AbortControlC
Move.L A0,D2
Bsr PrintN2Text
Bne .AbortControlC
.Done MoveM.L (Sp)+,D0-D1/A0-A3
Rts
.AbortControlC MoveQ #-1,D0
Bra .Done
;---------------------------------------------------------------
; Input: D0 = Number of space characters to output (up to 31).
;
PrintNSpaces MoveM.L D2-D3/A0-A3,-(Sp)
Lea Spaces(PC),A0
Move.L A0,D2
And.L #$1F,D0
Beq .Done
Move.L D0,D3
Bsr PrintCLI
.Done MoveM.L (Sp)+,D2-D3/A0-A3
Rts
Spaces Dc.B " "
;---------------------------------------------------------------
StripLeadingZeros
Tst.B 1(A0)
Beq .Done
Cmp.B #"0",(A0)
Bne .Done
Move.B #" ",(A0)+
Bra StripLeadingZeros
.Done Rts
;---------------------------------------------------------------
; VerifyPath routine. Takes a string which might be either a pathname or a
; filespec, tries to get a lock on it, and determines whether the string
; is a pathname, filespec, or garbage. I save a lot of registers in this
; routine because I just don't trust AmigaDOS (who would?).
;
; Input: A0 = Pathname or filespec string (NULL-Terminated).
;
; Output: D0 = 0 if string is a filespec.
; >0 if string is a pathname.
; <0 if string is bloody nonsense.
;
; Trashes: Nothing.
;
VerifyPath MoveM.L D1-D7/A0-A3/A5/A6,-(Sp) ;Speed's not important here. Play it safe.
MoveQ #-1,D6 ;Assume user will type nonsense. :)
Move.L DosBase(A4),A6 ;Get DOS_Base.
Move.L A0,D1 ;Ptr to string in D1.
MoveQ #-2,D2 ;Read only mode for lock.
SYS Lock ;Attempt to get a lock.
Move.L D0,LockPointer(A4) ;Save ptr to the lock.
Beq .Leave2 ;Couldn't get a lock. Error.
Move.L D0,D7 ;Cache lock pointer in D7.
Move.L D7,D1 ;Put it back in D1.
Move.L MyFileInfoBlock(A4),A0 ;Get ptr to FileInfoBlock.
Move.L A0,D2 ;DOS wants it in D2.
SYS Examine ;Fill out file info block.
Tst.L D0 ;Was the path/file found?
Beq .Leave ;Apparently not.
Move.L MyFileInfoBlock(A4),A0 ;Yes, get file info block again.
Tst.W fib_DirEntryType(A0) ;Check dir entry type.
Bmi .IsFile ;Negative means it's a file.
AddQ.L #1,D6 ;It's a path, inc D6.
.IsFile AddQ.L #1,D6 ;It's a file, inc D6.
.Leave Move.L LockPointer(A4),D1
SYS UnLock
.Leave2 Move.L D6,D0 ;Return status in D0.
MoveM.L (Sp)+,D1-D7/A0-A3/A5/A6 ;Restore regs.
Rts ;And leave.
;---------------------------------------------------------------
; GetFileSpec routine. Extracts a file specification from the command line
; args. Stores the extracted filespec in FilenameString[].
;
; Input: A5 = pointer to command line argstring.
;
; Output: FilenameString[] holds the extracted filespec.
; A5 pts to new current position in argstring.
; D0 = -1 if no filespec was specified in the argstring.
; 0 if argument begins with "?".
; +1 if FilenameString[] holds a valid string.
;
; Trashes: A0
;
GetFileSpec Lea FilenameString(A4),A0 ;A0 = ptr to dest string buffer.
.Skip Move.B (A5),D0 ;Get char from argstring.
Cmp.B #DQUOTE,D0 ;Is it a double quote?
Beq.S .DoQuote ;Yup, do special quote handling.
Cmp.B #"?",D0 ;Is it a ?
Beq .IsQMark ;Yup, Leave with return code of 0.
Cmp.B #" ",D0 ;Is it a space character?
Bgt .Copy ;No, ASCII value is greater than space char.
Cmp.B #TAB,D0 ;Is it a tab?
Beq .Skip ;Yup, ignore it.
Cmp.B #LF,D0 ;Have I reached the end of the argstring?
Beq .NoFileSpec ;Yup, no filespec was specified.
AddQ #1,A5 ;No, so ignore char and get another.
Bra .Skip
.DoQuote AddQ #1,A5 ;Skip past the double quote character.
Move.B (A5),D0 ;Get char from argstring.
Cmp.B #LF,D0 ;Reached EOL yet?
Beq .Done ;Yup, no close quote, but that's OK.
Cmp.B #DQUOTE,D0 ;Is it a (close) quote?
Beq .EndQuote ;Yup, fix up argstring ptr and leave.
Move.B D0,(A0)+ ;Nope, extract this character.
Bra .DoQuote ;And go get another.
.EndQuote AddQ #1,A5 ;Skip past the close quote.
Bra .Done ;And leave.
.Copy Move.B (A5)+,(A0)+ ;Copy a character from argstring into buffer.
Cmp.B #" ",(A5) ;Is next char a space?
Beq.S .Done ;Yup, NULL-terminate buffer and leave.
Cmp.B #TAB,(A5) ;Is next char a tab?
Beq.S .Done ;Yup, all done.
Cmp.B #LF,(A5) ;Nope, reached EOL yet?
Bne.S .Copy ;Nope, go copy next character.
.Done Clr.B (A0) ;NULL-terminate string in buffer.
MoveQ #1,D0 ;Indicate valid string in buffer.
.Leave Rts ;And leave.
.IsQMark MoveQ #0,D0 ;Indicate argument was "?"
Bra .Leave
.NoFileSpec MoveQ #-1,D0 ;Indicate no filespec was given.
Bra .Leave ;and leave.
;---------------------------------------------------------------
; PrintCLI routine. Prints a text string to the standard output.
;
; Input: D2 = Pointer to the text string to print (NOT NULL-terminated).
; D3 = Length of the text string.
;
; Output: Nothing.
;
; Trashes: D0,D1,D2,D3,A0,A1,A2
;
PrintCLI MoveM.L A0-A6,-(Sp)
Move.L OutputHandle(A4),D1
Move.L DosBase(A4),A6
SYS Write
; Before returning, check to see if CTRL-C has been pressed...
LOADLIB SYS
MoveQ #0,D0
MoveQ #0,D1
SYS SetSignal
Move.L #SIGBREAKB_CTRL_C,D1
BTst D1,D0
MoveM.L (Sp)+,A0-A6
Rts
;---------------------------------------------------------------
; PrintNText routine. Prints a NULL-terminated string to the standard output.
; Automatically appends a linefeed character to the end of the text output.
;
; Input: D2 = Pointer to the NULL-terminated text string to print.
;
; Output: Nothing.
;
; Trashes: D0,D1,D2,D3,A0,A1,A2
;
PrintNText Bsr PrintN2Text
Bne .Done
Move.L #LineFeed,D2
MoveQ #1,D3
Bsr PrintCLI
.Done Rts
LineFeed Dc.B LF,0
;---------------------------------------------------------------
; PrintN2Text routine. Prints a NULL-terminated string to the standard output,
; just like PrintNText above, but does not output a linefeed at the end.
;
; Input: D2 = Pointer to the NULL-terminated text string to print.
;
; Output: D0 = Nothing.
;
; Trashes: D0,D1,D2,D3,A0,A1,A2
;
PrintN2Text MoveQ #0,D3
Move.L D2,A0
.1 AddQ #1,D3
Tst.B (A0)+
Bne .1
SubQ #1,D3
Bsr PrintCLI
Rts
;---------------------------------------------------------------
; PrintTextMax routine. Prints a NULL-terminated string to the standard output,
; just like PrintNText, but does not output a linefeed at the end. Also takes
; a maximum number of characters as input. The string output will not be longer
; than this number.
;
; Input: D2 = Pointer to the NULL-terminated text string to print.
;
; Output: D0 = Nothing.
;
; Trashes: D0,D1,D2,D3,A0,A1,A2
;
PrintTextMax MoveQ #0,D3
MoveQ #0,D1
Move.W D0,D1
SubQ.W #1,D0
Move.L D2,A0
.1 AddQ #1,D3
Tst.B (A0)+
DBeq D0,.1
SubQ #1,D3
Cmp.W D1,D3
Blt .2
Move.L D1,D3
.2 Move.L D3,-(Sp)
Bsr PrintCLI
Move.L (Sp)+,D3 ;Return number of characters printed.
Exg D0,D3
BTst D1,D3
Rts
;---------------------------------------------------------------
; PrintNicely routine. Prints a NULL-Terminated text string one line at a time
; (using the PrintCLI routine above) so that the output can be paused by
; pressing a key. It is important to remember that the text string passed to
; this routine MUST have a linefeed character immediately preceding the
; terminating NULL.
;
; Input: D2 = Pointer to the text string to print (LF & NULL-terminated).
;
; Output: Nothing.
;
; Trashes: D0,D1,D2,A0,A1
;
PrintNicely MoveM.L D3/A2/A3/A5,-(Sp)
Move.L D2,A5
.NextLine Move.L A5,A3
MoveQ #0,D3
.CountChars AddQ #1,D3
Move.B (A3)+,D0
Beq .Done
Cmp.B #LF,D0
Bne .CountChars
Move.L A5,D2
Move.L A3,A5
Bsr PrintCLI
Bne .AbortControlC
Bra .NextLine
.Done MoveM.L (Sp)+,D3/A2/A3/A5
Rts
.AbortControlC MoveQ #-1,D0
Bra .Done
;---------------------------------------------------------------
; BinToDec routine. Converts an unsigned long into a decimal string
; that can be printed. The resultant string is NULL-Terminated.
;
; Input: D0 = unsigned longword to convert.
;
; Output: DecString[] holds the decimal string of the value.
;
BinToDec MoveM.L D0-D3/A0,-(Sp)
MoveQ #10-1,D1 ;Start with index for highest power of 10.
Lea DecString(A4),A0
.Loop Move.L D1,D2
Add.L D2,D2
Add.L D2,D2
Move.L PowerTable(PC,D2.W),D2 ;D2 holds current power of 10.
MoveQ #-1,D3
.1 AddQ.W #1,D3
Sub.L D2,D0
Bpl .1
Add.L D2,D0
Add.B #"0",D3 ;D3 holds ASCII digit.
Move.B D3,(A0)+ ;Store digit in string.
DBra D1,.Loop
Clr.B (A0)
MoveM.L (Sp)+,D0-D3/A0
Rts
PowerTable Dc.L 1
Dc.L 10
Dc.L 100
Dc.L 1000
Dc.L 10000
Dc.L 100000
Dc.L 1000000
Dc.L 10000000
Dc.L 100000000
Dc.L 1000000000
;---------------------------------------------------------------
; BinToTime routine. Converts a longword number of ticks (units of
; 1/60 second) into a string of the form "00:00:00:00"...
;
; Input: D0.L = unsigned longword value to convert.
;
; Output: TimeString holds the time string of the value.
;
BinToTime MoveM.L D2-D3/A2,-(Sp)
Move.L D0,D2
Lea TimeString(A4),A2
; Calculate number of hours...
Move.L #216000,D1
MoveQ #0,D3
.HoursLoop AddQ #1,D3
Sub.L D1,D2
Bpl .HoursLoop
Add.L D1,D2
SubQ #1,D3
Move.L D3,D0
Bsr BinToDec
Lea DecString+8(A4),A0
Move.B (A0)+,(A2)+
Move.B (A0)+,(A2)+
Move.B #":",(A2)+
; Calculate number of minutes...
Move.L #3600,D1
MoveQ #0,D3
.MinutesLoop AddQ #1,D3
Sub.L D1,D2
Bpl .MinutesLoop
Add.L D1,D2
SubQ #1,D3
Move.L D3,D0
Bsr BinToDec
Lea DecString+8(A4),A0
Move.B (A0)+,(A2)+
Move.B (A0)+,(A2)+
Move.B #":",(A2)+
; Calculate number of seconds...
MoveQ #60,D1
MoveQ #0,D3
.SecondsLoop AddQ #1,D3
Sub.L D1,D2
Bpl .SecondsLoop
Add.L D1,D2
SubQ #1,D3
Move.L D3,D0
Bsr BinToDec
Lea DecString+8(A4),A0
Move.B (A0)+,(A2)+
Move.B (A0)+,(A2)+
Move.B #":",(A2)+
; Calculate number of jiffies...
Move.L D2,D0
Bsr BinToDec
Lea DecString+8(A4),A0
Move.B (A0)+,(A2)+
Move.B (A0)+,(A2)+
Clr.B (A2)
MoveM.L (Sp)+,D2-D3/A2
Rts
;---------------------------------------------------------------
; ReportLibErr routine. Takes a library return code and turns it into
; an error message that is displayed to the user.
;
; Input: D0 = Library return code.
;
; Output: Nothing.
ReportLibErr Tst.L D0 ;Did an error actually occur?
Bpl .Done ;Nope.
Neg.W D0 ;Make return code positive.
SubQ #1,D0 ;Code now in 0..n range.
Add.W D0,D0 ;Make longword index out of it.
Add.W D0,D0
Lea ErrorLookup,A0 ;Ptr to err msg addr lookup table.
Move.L 0(A0,D0.W),D2 ;Get ptr to the error message.
Bsr PrintNicely ;And print it.
MoveQ #-1,D0 ;Return general failure code.
.Done Rts ;That was easy.
;==============================
DATA
Even
; Lookup table for error message string addresses...
ErrorLookup Dc.L Owned
Dc.L DummyText
Dc.L DummyText
Dc.L DummyText
Dc.L DummyText
Dc.L LoadErr
Dc.L NoMem
Dc.L BadPath
Dc.L Format
Dc.L DummyText
Dc.L DummyText
Dc.L NotFoundErr
Dc.L MInstsErr
Dc.L DummyText
; Error messages...
DummyText
Owned Dc.B LF,"ERROR: Library has been owned by another prog.",LF,LF,NULL
LoadErr Dc.B LF,"ERROR: Could not load file.",LF,LF,NULL
NoMem Dc.B LF,"ERROR: Insufficient memory.",LF,LF,NULL
BadPath Dc.B LF,"ERROR: Illegal pathname.",LF,LF,NULL
Format Dc.B LF,"ERROR: Unrecognized module format.",LF,LF,NULL
NotFoundErr Dc.B LF,"ERROR: File not found.",LF,LF,NULL
MInstsErr Dc.B LF,"ERROR: Module is missing instrument(s).",LF,LF,NULL
NoModuleText Dc.B LF,"ERROR: No module is currently loaded.",LF,LF,NULL
InsuffMemText Dc.B LF,"ERROR: Insufficient memory.",LF,LF,NULL
NotFileText Dc.B LF,"ERROR: filespec must specify a file, not a directory.",LF,LF,NULL
NoLibOpenText Dc.B LF,"ERROR: You need destracker.library v3.0 or higher.",LF,LF,NULL
; Title, copyright, and usage text...
HelloText Dc.B LF,"destracker.library Module Info program",LF
Dc.B "Copyright (c)1993 by Darren Schebek",LF
Dc.B "Version 2.0 Dec 18, 1993",LF,LF
Dc.B "usage: modinfo {filespec} Load mod & report stats",LF
Dc.B " modinfo Report on current mod",LF
Dc.B " modinfo ? Show usage",LF,LF
Dc.B NULL
; Various text used for reporting statistics...
ModInfoForFile Dc.B LF,"Module information for file: ",NULL
TitleText Dc.B LF," Title: ",NULL
PTimeText Dc.B "mJuke Play Time: ",NULL
FLengthText Dc.B " File Length: ",NULL
FormatText Dc.B " Format: ",NULL
HasPSC0Text Dc.B " Has PSC0: ",NULL
BaseTimingText Dc.B " Base Timing: ",NULL
TempoIntText Dc.B " Tempo Interp: ",NULL
DefTempoText Dc.B " Def. Tempo: ",NULL
DefFTempoText Dc.B " Def. FTempo: ",NULL
IterationsText Dc.B " # Iterations: ",NULL
NumPattsText Dc.B " # Patterns: ",NULL
NumPosText Dc.B " # Positions: ",NULL
NumInstsText Dc.B " # Instruments: ",NULL
InstDataText Dc.B LF,"Instrument Data:",LF,LF
Dc.B "Number Name Length RepOffset RepLen Volume",NULL
UnusedText Dc.B " *** Unused Instrument ***",LF,NULL
MinusText Dc.B "-"
DTFormat Dc.B "DES-Tracker v1.0",NULL
STFormat Dc.B "Soundtracker v2.6",NULL
NTFormat Dc.B "Noise/Protracker",NULL
YesText Dc.B "Yes",NULL
NoText Dc.B "No",NULL
NTSCText Dc.B "NTSC",NULL
PALText Dc.B "PAL",NULL
UnknownText Dc.B "Unknown",NULL
StandardText Dc.B "Standard",NULL
BPMText Dc.B '"Beats Per Minute"',NULL
InfiniteText Dc.B "Infinite",NULL
; Library names used for OpenLibrary()...
DosName Dc.B "dos.library",0
DTLName DTLIBNAME
Even
End